package com.codeoss.framework.report.query;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.expression.IScriptService;
import com.codeoss.framework.expression.IScriptServiceStore;

@Service
public class QueryDefService implements IQueryDefService {
	@Autowired
	private IQueryDefStore queryDefStore;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private IScriptServiceStore scriptServiceStore;
	
	@Override
	public List<Map<String, Object>> search(String code, Map<String, Object> paraMap) {
		// TODO Auto-generated method stub
		QueryDef queryDef=queryDefStore.get(code);
		Element element=queryDef.getElement();
		StringBuilder sql=new StringBuilder();
		NodeList children=element.getChildNodes();
		List<Object> paraValueList=new ArrayList<Object>();
		for(int i=0;i<children.getLength();i++) {
			Node node=children.item(i);
			short type=node.getNodeType();
			if(Node.TEXT_NODE==type) {
				String textContent=node.getTextContent();
				String text=parseText(textContent,paraMap,paraValueList);
				sql.append(text);
			}else if(Node.ELEMENT_NODE==type) {
				Element childElement=(Element)node;
				String tagName=childElement.getTagName();
				if("if".equals(tagName)) {
					String test=childElement.getAttribute("test");
					Expression expression=new Expression();
					expression.setScriptType(Expression.EXPRESSION_TYPE_JAVASCRIPT);
					expression.setScript(test);
					IScriptService scriptService=scriptServiceStore.getScriptService(expression);
					boolean result=(boolean)scriptService.eval(test, paraMap);
					if(result) {
						String textContent=childElement.getTextContent();
						String sqlSnippet=parseText(textContent, paraMap, paraValueList);
						sql.append(sqlSnippet);
					}
				}
			}
		}
		List<Map<String,Object>> list=jdbcTemplate.queryForList(sql.toString(), paraValueList.toArray());
		return list;
	}

	private String parseText(String text, Map<String, Object> paraMap,List<Object> paraValueList) {
		int index=text.indexOf("#");
		if(index==-1) {
			return text;
		}
		StringBuilder sql=new StringBuilder();
		int from=0;
		while(index!=-1) {
			sql.append(text.substring(from,index));
			int start=text.indexOf("{", index);
			int end=text.indexOf("}",index);
			String paraName=text.substring(start+1,end);
			Object value=paraMap.get(paraName);
			paraValueList.add(value);
			sql.append("?");
			from=end+1;
			index=text.indexOf("#", from);
		}
		if(from<text.length()) {
			sql.append(text.substring(from));
		}
		return sql.toString();
	}
}
